#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <boost/program_options.hpp>
#include <string>
#include <cmath>
#include "get_arg.h"


// link with -lboost_filesystem-gcc -lboost_program_options-gcc  -lboost_regex-gcc -lcomponents
// program_options_helper.cpp

// my functions
#define DEBUG_LEVEL 6
#include <debug_func.h>
#include <matrix_formats.h>
#include <print_error.h>
#include <program_options_helper.h>

#include <boost/algorithm/string/find.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/regex.hpp>

using std::string;
using std::cerr;
using boost::algorithm::find_first;
using namespace program_options_helper;
namespace po = boost::program_options_lg;


bool process_command_line_options(int argc, char* argv[], t_program_args& args)
{

	// mandatory arguments
	string matrix_file_name;
	po::options_description mandatory_args("Mandatory Arguments");
	mandatory_args.add_options()
	("x_taxon_regex,x", po::value<string>(&args.taxon1)->set_name("REGEX"),
									"Regular expression to identify members of the first taxon.")
	("y_taxon_regex,y", po::value<string>(&args.taxon2)->set_name("REGEX"),
									"Regular expression to identify members of the second taxon.");



	// optional arguments
	args.optional_args.add_options()
	("x_taxon_name,X", po::value<string>(&args.taxon1_name)->set_name("STRING")
									 ->default_value("taxon1"),
									"Name of the first taxon.")
	("y_taxon_name,Y", po::value<string>(&args.taxon2_name)->set_name("STRING")
									 ->default_value("taxon2"),
									"Name of the second taxon.")
	("output_path,o", po::value<string>(&args.out_path_format)
												->set_name("PATH")
												->default_value("[FILENAME][EXT]"),
								 "Use PATH to specify the name and location of the output "
									"files.")
	("orphaned_clades,O", po::value<string>(&args.orphaned_clades)
												->set_name("FILE"),
								 "Specify the file to hold clades of orphans.")
	("no_breakdown,N",			po::bool_switch(&args.no_breakdown_by_ortholog_type),
									"Do not break down ortholog predictions by type "
									"(1:1 orthologue or orphans etc.)");



	args.add_std_options();
	po::options_description all_args("");
	all_args.add(mandatory_args).add(args.optional_args);

	// parse command line
	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv).options(all_args).run(), vm);
	po::notify(vm);

	if (vm.count("version"))
	{
		print_version(cerr, *argv, "1.0\n"
			"\tHistory: \n\n"
			"\tv 1.0\1"
			"Initial version\n"
//			"\tv 1.1\1"
//			"01-02-2005\1"
//			"Split programme so that vanilla version does not do anything with matrices.\n"
			);
		return false;
	}
	if (vm.count("help"))
	{
		string exe_description =
			"Takes trees in New Hamshire format from STDIN "
				"and derives the orthology relationships.\n"
			"A tab-delimited list of orthologs prefixed by dS is printed to STDOUT\n"
			"In addition, the following files are created:\1"
				"gene.counts\1"
				"full_topology.tree\1"
				"all_nodes.list\1"
				"ortho_1_to_1.data\1"
				"ortho_1_to_m.data\1"
				"ortho_m_to_1.data\1"
				"ortho_m_to_m.data\1"
				"orphaned_tax1.data\1"
				"orphaned_tax2.data\n"
			"The list of all orthologues is output to STDOUT\n"
			"The file location are specified with --output_path where [FILENAME] and "
			"[EXT] refer to their names and extensions.\1"
			"E.g.\1"
			"    --output_path \"/home/user/cow.[FILENAME]_07[EXT].test\"\1"
			"    would produce:\1"
			"    /home/user/cow.gene_07.counts.test\1"
			"    /home/user/cow.full_topology_07.tree.test\1"
			"    /home/user/cow.all_nodes_07.list.test\1"
			"    etc.\n";
		print_usage(cerr, string(*argv), "[OPTIONS] < TREE",
							all_args, exe_description, 80);
		return false;
	}

	
	check_required_options(vm, mandatory_args);
	if (!find_first(args.out_path_format,  string("[FILENAME]")))
	{
		throw std::runtime_error("Please include \"[FILENAME]\" in --output_path ('" + 
								 args.out_path_format + "')");
	}
	try
	{
		boost::regex try_regex(args.taxon1);
	}
	catch(std::exception& e)
	{
		throw std::runtime_error("Invalid regular expression specified in --xtaxon:\n" +
										string(e.what()));
	}
	try
	{
		boost::regex try_regex(args.taxon2);
	}
	catch(std::exception& e)
	{
		throw std::runtime_error("Invalid regular expression specified in --ytaxon:\n" +
										string(e.what()));
	}
	args.open_err_log();


	return true;
}







